package drds.global_transaction.api.message_codec;

import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import drds.global_transaction.api.message_codec.message_codec.Message;
import drds.global_transaction.api.message_codec.message_codec.MessageCodecs;
import drds.global_transaction.api.message_codec.request_and_response.RequestMessage;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class MergeWarpMessage extends Message implements Serializable, IMergeMessage
{
	private static final long serialVersionUID = -1L;
	@Setter
	@Getter
	public List<RequestMessage> messageList = new ArrayList<RequestMessage>();
	@Setter
	@Getter
	public List<Long> rpcMessageIdList = new ArrayList<Long>();

	@Override
	public short getTypeCode()
	{
		return type_merge_warp;
	}

	@Override
	public byte[] encode()
	{
		int bufferSize = messageList.size() * 1024;
		ByteBuffer byteBuffer = ByteBuffer.allocate(bufferSize);
		byteBuffer.putShort((short) messageList.size());
		for (Message message : messageList)
		{
			byte[] bytes = message.encode();
			byteBuffer.putShort(message.getTypeCode());
			byteBuffer.put(bytes);
		}
		byteBuffer.flip();
		int length = byteBuffer.limit();
		byte[] bytes = new byte[length + 4];
		//
		intToBytes(length, bytes, 0);
		//
		byteBuffer.get(bytes, 4, length);
		return bytes;
	}

	@Override
	public boolean decode(ByteBuf byteBuf)
	{
		int readableBytes = byteBuf.readableBytes();
		if (readableBytes < 4)
		{
			return false;
		}

		readableBytes -= 4;
		int length = byteBuf.readInt();
		if (readableBytes < length)
		{
			return false;
		}

		byte[] bytes = new byte[length];
		byteBuf.readBytes(bytes);
		ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
		doDecode(byteBuffer);
		return true;
	}

	private void doDecode(ByteBuffer byteBuffer)
	{
		short messageNum = byteBuffer.getShort();
		for (int index = 0; index < messageNum; index++)
		{
			short typeCode = byteBuffer.getShort();
			IMergedMessage mergedMessage = (IMergedMessage) MessageCodecs.getMessageCodec(typeCode);
			mergedMessage.decode(byteBuffer);
			messageList.add((RequestMessage) mergedMessage);
		}
	}

}
